package org.op.service.nav;

import java.io.File;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;

import org.op.service.WwDocumentInfo;
import org.op.service.WwFolderInfo;
import org.op.service.WwInfoObject;


public class FileNavigationServiceImpl implements FileNavigationService {

	public TreeModel loadTreeRoot(TreeModel model, String workspace) {
		
		DefaultMutableTreeNode top = new DefaultMutableTreeNode("Notes");
		WwFolderInfo tfi = new WwFolderInfo("Notes", workspace);
		tfi.setExpanded(true);
		top.setUserObject(tfi);
		
		if (model!=null && model.getRoot()!=null) {
			top = (DefaultMutableTreeNode) model.getRoot();
		} else {
			model = new DefaultTreeModel(top);
		}
		
		top = getExpandedNode(top);
		
		return model;
	}
	
	/**
	 *  This is a recursive method to get the children of the specified node, and
	 *    add to the tree model, as necessary (creating the Node object, if necessary)
	 * 
	 *  TODO - this method is too long, refactor
	 * 
	 * @param node
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private DefaultMutableTreeNode getExpandedNode(DefaultMutableTreeNode node) {
		
		if (node.getUserObject() instanceof WwFolderInfo) {
			WwFolderInfo folderInfo = (WwFolderInfo) node.getUserObject();
			System.out.println("Expanding folder " + folderInfo.getName());
			
			// Get the current list of folders and documents, to maintain state
			Map<String, DefaultMutableTreeNode> existingDocuments = new HashMap<String, DefaultMutableTreeNode>();
			Map<String, DefaultMutableTreeNode> existingFolders = new HashMap<String, DefaultMutableTreeNode>();
			
			// Get the children of the existing model
			Enumeration<DefaultMutableTreeNode> children = node.children();  // existing children
			while (children.hasMoreElements()) {
				DefaultMutableTreeNode child = children.nextElement();
				WwInfoObject infoObject = (WwInfoObject) child.getUserObject();
				if (infoObject instanceof WwDocumentInfo) {
					existingDocuments.put(infoObject.getName(), child);
					System.out.println("* Existing document = " + infoObject.getName());
				}
				if (infoObject instanceof WwFolderInfo) {
					existingFolders.put(infoObject.getName(), child);
					System.out.println("* Existing folder = " + infoObject.getName());
				}
			}

			node.removeAllChildren(); // to refresh
			
			// Get the children of the associated folder in the filesystem
			File parent = new File(folderInfo.getFilepath());
			if (parent.exists()) {		
				File[] files = parent.listFiles();
				for (File child: files) {
					if (isValidWikiFile(child)) {
						String fileName = child.getName();
						
						// eliminate the file extension
						// TODO - this will choke if there is a folder in the path with a period
						int i = fileName.indexOf('.');
						fileName = fileName.substring(0,i);
						System.out.println("* File child = " + fileName);
						
						DefaultMutableTreeNode childNode = existingDocuments.get(fileName);
						if (childNode==null) {
							System.out.println("** is a new file.");
							childNode = new DefaultMutableTreeNode(fileName);
							WwDocumentInfo tdi = new WwDocumentInfo(fileName, child.getAbsolutePath());
							childNode.setUserObject(tdi);
						}
	
						node.add(childNode);
					} 
					if (child.isDirectory()) {
						String folderName = child.getName();
						System.out.println("* Folder child = " + folderName);
						DefaultMutableTreeNode childNode = existingFolders.get(folderName);
						if (childNode==null) {
							System.out.println("** is a new folder.");
							childNode = new DefaultMutableTreeNode(folderName);
							WwFolderInfo tfi = new WwFolderInfo(folderName, child.getAbsolutePath());
							childNode.setUserObject(tfi);
							childNode.setAllowsChildren(true);
						}
						node.add(childNode);
						
						// recurse down this folder
						getExpandedNode(childNode);
					}
				}
			}
		}
		
		return node;
	}

	/**
	 * Filter invalid files
	 * 
	 * @param child
	 * @return
	 */
	private boolean isValidWikiFile(File child) {
		boolean valid = false;
		
		if (child.isFile()) {
			String fileName = child.getName();
			if (fileName.endsWith(".txt")) {
				valid = true;
			}
		}
		
		return valid;
	}

	public WwInfoObject getAssociatedInfo(TreeNode node) {
		
		WwInfoObject wwInfo = null;
		if (node instanceof DefaultMutableTreeNode) {
			wwInfo = (WwInfoObject) ((DefaultMutableTreeNode)node).getUserObject();
		}
		
		return wwInfo;
		
	}


}
